3.3 现代风格:TTK

ttk 是Tk 8.5版本开始加入的模块。在之前,我们学习的小控件外观看起来都很陈旧过时,编写的界面会比较丑陋。而ttk模块的出现正是为了解决这个问题,它使小控件的外观更接近于系统平台所特定的外观,不仅如此,它还能支持主题的定制,使我们能更简便的改进界面的美观程度。

TTK的使用

如果是使用from tkinter import *方式导包,则只需在其下增加from tkinter.ttk import *即可应用ttk风格。使用ttk模块后,小控件外观会产生差别。

from tkinter import *
# 增加如下导包语句即可
from tkinter.ttk import *

root = Tk()
root.geometry("300x300")

top = LabelFrame(root, text="Label")
top.pack(padx=8, pady=8)
Label(top, text="我是标签,哈哈").pack()

body = LabelFrame(root, text="Button")
body.pack(padx=8, pady=8)
Button(body, text="你点啊").pack()

bottom = LabelFrame(root, text="其他")
bottom.pack(padx=8, pady=8)
Checkbutton(bottom, text="唱歌").pack()
Checkbutton(bottom, text="跳舞").pack()
Checkbutton(bottom, text="健身").pack()

Scale(bottom, orient='horizonta', from_=0, to=100).pack()

root.mainloop()

如使用其他方式导包,则需指定ttk模块控件

import tkinter as tk
import tkinter.ttk as ttk

root = tk.Tk()

ttk.Label(root, text="标签").pack()
ttk.Button(root, text="点啊").pack()

root.mainloop()

ttk仅支持11个原核心控件

  • Button
  • Checkbutton
  • Entry
  • Frame
  • Label
  • LabelFrame
  • Menubutton
  • PanedWindow
  • Radiobutton
  • Scale
  • Scrollbar

TTK 新增控件

ttk 新增了6个控件,这里我们主要介绍4个重要的

  • Combobox 输入框下拉选项菜单
  • Progressbar 进度条控件
import tkinter as tk
import tkinter.ttk as ttk

root = tk.Tk()
ttk.Label(root, text="编程语言").pack(side=tk.LEFT, padx=5, pady=5)

combo = ttk.Combobox(root, values=["Go", "Python", "Java", "C++"])
# 设置当前选中的项
combo.current(1)
combo.pack(side=tk.LEFT, padx=5, pady=5)

# 创建进度条控件
progress = ttk.Progressbar(root, mode='indeterminate', length=100)
progress.pack(pady=10, padx=10)

# 启动进度条控件
progress.start()

progress2 = ttk.Progressbar(root, mode='determinate', length=100)
progress2.pack(pady=10, padx=10)
progress2.start()

root.mainloop()

Progressbar 参数说明:

  • mode

    有两个值可选。"indeterminate"表示来回反弹样式,"determinate"表示步进样式


  • Notebook 选项卡控件
import tkinter as tk
from tkinter.ttk import *

root = tk.Tk()
root.geometry("300x300")

notebook = Notebook(root)

page1 = tk.Frame(notebook, background="yellow")
Label(page1, text="这是 tab1 的界面").pack()


page2 = tk.Frame(notebook,  background="pink")
Label(page2, text="这是 tab2 的界面").pack()


notebook.add(page1, text="Tab1")
notebook.add(page2, text="Tab2")
notebook.pack(fill=tk.BOTH, expand="yes")

root.mainloop()
  • Treeview 树形控件

树形结构简单示例

import tkinter as tk
from tkinter import ttk


def item_select(event):
    for select in tree.selection():
        print(tree.item(select, "text"))

root = tk.Tk()
tree = ttk.Treeview(root, show='tree')

# 监听tree中item被选中的事件
tree.bind("<<TreeviewSelect>>", item_select)

# 第一个参数为父节点, 第二个为此项在父节点中的位置(父节点为空时,默认为根节点)
item1 = tree.insert("", 0, text="广东省")

# 在第一个节点中插入如下子节点
tree.insert(item1, 0, text="广州市")
tree.insert(item1, 1, text="深圳市")

item2 = tree.insert("", 1, text="湖北省")
tree.insert(item2, 0, text="武汉市")

tree.pack()
root.mainloop()

Treeview 制作表格

import tkinter as tk
from tkinter import ttk


def item_select(event):
    for select in tree.selection():
        print(tree.item(select, "values"))


def head_onclick(type):
    print(type)

root = tk.Tk()

# show用于禁止列顶部标签。columns用于设置每一列的列标识字符串
tree = ttk.Treeview(root, show='headings', columns=['0', '1', '2'])

# 监听tree中item被选中的事件
tree.bind("<<TreeviewSelect>>", item_select)

# 设置表头名称
tree.heading(0, text='序号', command=lambda: head_onclick('序号'))
tree.heading(1, text='姓名', command=lambda: head_onclick('姓名'))
tree.heading(2, text='年龄', command=lambda: head_onclick('年龄'))

# 设置每列中元素的样式
tree.column(0, anchor='center')
tree.column(1, anchor='center')
tree.column(2, anchor='center')

# "end" 表示往父节点的最后一个位置插入
item1 = tree.insert("", "end", values=("1", "赵二", "19"))
item1 = tree.insert("", "end", values=("2", "张三", "20"))
item1 = tree.insert("", "end", values=("3", "李四", "22"))
item1 = tree.insert("", "end", values=("4", "王五", "18"))

tree.pack()
root.mainloop()

Treeview 参数说明:

  • show

    用于禁止列顶部标签。有两个值,'tree'表示禁止每一列的顶部标签栏,'headings'表示禁止首列显示。


设置主题与样式

在使用ttk控件时,会发现它的控件不支持 bgfgborder 这样涉及样式的属性,这是因为它对外观样式进行了重新定义。

ttk 对外观样式的抽象共有三个级别

  • 主题
  • 样式
  • 状态样式

主题的查询与切换

from tkinter import ttk

style = ttk.Style()
# 获取所有支持的主题
print(style.theme_names())

# 获取当前使用的主题
print(style.theme_use())

# 切换主题
style.theme_use("classic")

样式与控件状态样式的定制

ttk中,控件实际上是一个字符串,要改变控件样式,需要指定这个字符串名称,而不是类名,它们的对应关系如下

类名 控件样式名
Button TButton
Checkbutton TCheckbutton
Combobox TCombobox
Entry TEntry
Frame TFrame
Label TLabel
LabelFrame TLabelFrame
Menubutton TMenubutton
Notebook TNotebook
PanedWindow TPanedwindow
Progressbar Horizontal.TProgressbar或Vertical.TProgressbar
Radiobutton TRadiobutton
Scale Horizontal.TScale 或 Vertical.TScale
Scrollbar Horizontal.TScrollbar 或Vertical.TScrollbar
Separator TSeparator
Sizegrip TSizegrip
Treeview Treeview

需要注意,在创建新样式时,应当定义newName.oldName形式的名称

from tkinter import Tk
from tkinter import ttk

root = Tk()

style = ttk.Style()

# 定义一个全局样式作为默认样式("."表示此样式将应用于顶级窗口及其所有子元素)
style.configure('.', font='Arial 14', foreground='brown', background='yellow')

# 未指定样式时,使用全局默认样式
ttk.Label(root, text='我没有指定样式').pack()

# 定义一个名为danger的新样式(newName.oldName格式)
style.configure('danger.TButton', font='Times 12', foreground='red', padding=1)
ttk.Button(root, text='我使用danger样式',  style='danger.TButton').pack()

# 为小控件的不同状态指定样式
style.map("new_state_style.TButton", foreground=[('pressed', 'red'), ('active', 'blue')])
ttk.Button(text="不同状态不同样式", style="new_state_style.TButton").pack()

# 覆盖Entry的当前主题(即使没有指定样式,也会受到主题更改的影响)
current_theme = style.theme_use()
style.theme_settings(current_theme,
                     {"TEntry": {
                         "configure": {"padding": 10},
                         "map": {"foreground": [("focus", "red")]}}})


ttk.Entry().pack()

root.mainloop()

results matching ""

    No results matching ""